#ifndef _ARCH_OVERFLOW_
#define _ARCH_OVERFLOW_

#include "arch_datos.h"
#include "buffer.h"
#include "header.h"
#include "arch_espacios_libres.h"
#define SIN_CAMBIOS		-1
#define SIN_ELEMENTOS   -2

class ArchOverflow : public ArchivoDatos{
	
	private:
		
		ArchEspaciosLibres* espacios_libres;
		
		/*
		 * Busca el bloque en que debe ingresar el registro, si es necesario
		 * crea un bloque nuevo.
		 */
		void poner_reg_en_bloque( int pos,TipoStruct* reg);
		
		bool poner_reg_en_bloque(Bloque* bloque, TipoStruct* reg){return false;}
		
		/*
		 * Me devuelve la posicion del sigueinte bloque con respecto al pasado por param
		 */
		unsigned int get_siguiente(Bloque* bloque_actual);
		
		/*
		 * Me devuelve la posicion del bloque anterior con respecto al pasado por param
		 */
		unsigned int get_anterior(Bloque* bloque_actual);
		
		/*
		 * modifico la posicion del bloque anterior al pasado por param,es el bloque ant en la lista
		 */
		void set_anterior(Bloque* bloque, unsigned int ant);
		
		/*
		 * modifico la posicion del siguiente bloque al pasado por param, donde continua la lista
		 */ 
		void set_siguiente(Bloque* bloque, unsigned int sig);
		
		int sacar_reg_bloque(Bloque* bloque, TipoStruct * reg, unsigned int pos_reg, unsigned int tam_reg);
		
		void concatenar(std::vector<TipoStruct*> &v1, std::vector<TipoStruct*> &v2);
	
		Bloque* obtener_bloque_nuevo();
		
		/*
		 * Devuelve la cantidad de registros en el bloque pasado como param.
		 */
		unsigned int get_cant_regs_bloque(Bloque* bloque);
			
	public:

		ArchOverflow(std::string& nombre, unsigned int tam_bloque);
		
		virtual ~ArchOverflow();
		
		/*
		 * Crea el archivo de overflows asi como todos sus auxiliares
		 */
		virtual void crear(std::string formato) throw(ExcepCreandoArch, ExcepSintaxisParser, ExcepBloqueTam); 
		
		/*
		 * Abre el archivo
		 */
		void abrir() throw(ExcepAbriendoArch);
		
		/*
		 * Cierra el archivo y todos sus auxiliares
		 */
		virtual void cerrar();
 		
 		/*
 		 * Elimina el archivo fisicamente.
 		 */
 		virtual void eliminar();
		
		
		/*
		 * Ingresa en la posicion pasada por parametro el registro dado.
		 * Internamente resuelve los encadenamientos.
		 */ 
		virtual void ingresar(int pos,TipoStruct * reg) throw(ExcepArchCerrado,ExcepRegExistente, ExcepBloqueTam);
		
		/*
		 * Quita el registro pasado por parametro que se encuentra en
		 * la posicion dada
		 */
		virtual int quitar(unsigned int pos, TipoStruct * reg) throw(ExcepArchCerrado);
		
		/* Devuelve todos los elementos en resultado que se encuentran
		 * en la posicion pasada por param
		 */ 
		virtual void consultar_todos(unsigned int pos, std::vector<TipoStruct*> &resultado)throw(ExcepLeerBloque);
 		
 		/*
 		 * Deuelve el numero del primer bloque libre
 		 */
 		unsigned int get_primer_bloque_libre();
 		
 		/*
 		 * Devuelve el tamanio libre del archivo en cantidad de bytes.
 		 */
 		unsigned int get_espacio_libre() throw(ExcepArchCerrado, ExcepLeerBloque);
 		
 		/*
 		 * Devuelve la cantidad de registros en el archivo.
 		 */
 		unsigned int get_cant_regs() throw(ExcepArchCerrado);
 		
		/*
		 * Devuelve el espacio libre en bytes del indice primario.
		 */ 
		virtual unsigned int get_esp_libre_indice()  throw(ExcepArchCerrado, ExcepLeerBloque);
		 
		/*
		 * Devuelve la cantidad de registros del indice primario.
		 */ 										
		virtual unsigned int get_cant_regs_indice() throw(ExcepArchCerrado);
		
		/*
 		 * Devuelve el tamanio ocupado total por el indice primario, en bytes.
 		 */ 
 		virtual long get_tam_arch_indice() throw(ExcepArchCerrado);
 		
 		virtual unsigned int get_tamanio_serializado(TipoStruct* reg);
 		
 		void set_cant_bloques_header(unsigned int cant);
 		
 		unsigned int get_cant_bloques_header();
 		
 		void set_cant_regs_bloque(Bloque* bloque, unsigned int cant);
 		
 		TiposArchivo get_tipo_archivo();
 		
 		void ingresar(TipoStruct * reg) throw(ExcepArchCerrado,ExcepRegExistente, ExcepBloqueTam){}
		void quitar(std::vector<ParesDatos*> &elementos, std::vector<TipoStruct*> &resultado) throw(ExcepArchCerrado){}
		void consultar(std::vector<ParesDatos*> &consultas, std::vector<TipoStruct*> &resultado)
									 throw(ExcepArchCerrado,ExcepLeerBloque){}
 		void actualizar(TipoStruct * reg) throw(ExcepArchCerrado,ExcepRegInexistente,ExcepBloqueTam){}
 		
 		/*
		 * Devuelve la primera posicion donde se encuentran los registros
		 * en el archivo, es decir, luego de los tags de control
		 */ 
		unsigned int get_primera_pos(){
			return 0;
		}
 		
 
 };
 	
#endif //_ARCH_OVERFLOW_
